﻿namespace Lilium.CSharp.Expressions

module Evaluators = 
    
    open System.Reflection

    open Lilium.CSharp.Expressions.Patterns

    let rec Eval = function 
        | Call (met, null, args)    ->  met.Invoke (null, args |> List.map Eval |> Array.ofList)
        | Call (met, obj, args)     ->  met.Invoke (Eval obj, args |> List.map Eval |> Array.ofList)
        | Constant (value, _)       ->  value
        | Convert (value, _)        ->  Eval value
        | Invoke (expr, args)       ->  Eval expr //TODO: превратить в лямбду может быть, или выполнить подстановку аргументов
        | Lambda (expr, args)       ->  Eval expr //TODO: подставить аргументы (вообще их можно передавать в контекст)
        | MemberAccess (memb, obj)  ->  match memb.MemberType with
                                        | MemberTypes.Property
                                            ->  let property = memb :?> PropertyInfo
                                                property.GetValue (Eval obj, null)
                                        | MemberTypes.Field
                                            ->  let field = memb :?> FieldInfo
                                                field.GetValue(Eval obj)
                                        | other 
                                            ->  failwithf "Accessing member of type %O is not supported" other 
        
        | other ->  failwithf "Evaluation of expression of type %O is not supported" other.NodeType